////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//  Filename:    PrinceOfSherwoodGuts.h                                       //
//  Developer:   George Chapman                                               //
//  Create date: 01/10/2005                                                   //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//  Description: This is the class implementation for the slot gut for the    //
//               Australian Slot machine called Prince Of Sherwood.           //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
//        Copyright (c) 2004 - Realtime Gaming.  All rights reserved.         //
////////////////////////////////////////////////////////////////////////////////

#include "PrinceOfSherwoodGuts.h"

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::PrinceOfSherwoodGuts()   
///
/// This is the default constructor for the class.
////////////////////////////////////////////////////////////////////////////
PrinceOfSherwoodGuts::PrinceOfSherwoodGuts() 
{
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::~PrinceOfSherwoodGuts()   
///
/// This is the destructor for the class.
////////////////////////////////////////////////////////////////////////////
PrinceOfSherwoodGuts::~PrinceOfSherwoodGuts() 
{
}
    
////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::classifyStops()   
///
/// @param   stops      The array of stop positions for the line.
/// @param   bet        The value of the line bet.
/// @param   line       The index of the line.
///
/// @return	 uint8      A payout from the SpinResult enumeration as a uint8.    
///
/// This helper method is used to calculate the payout on a line.
////////////////////////////////////////////////////////////////////////////
void
PrinceOfSherwoodGuts::classifyStops(SpinLine* spinline, uint8* stops,uint8 bet, uint8 line, uint8& rtnresult, uint8& multiplier)
{
	SpinResult result              = EVT_LOSER; // spin result :)
	uint8      testIcon            = BLANK;     // Icon at current position
	uint8      iconThatIsNotRobin  = BLANK;     // Holder for an Icon that is NOT Robin
    bool8      hasRobin            = false;     // Indicates if Robin Hood is part of the evaluation

    // By default everything pays at a x1 multiplier
    multiplier = 1;

	//Now, go through the rest, until the streak is over
	for ( uint8 i = 0; (i < getReelCount()); i++ )
    {
		testIcon = getIcon(getGameModeId(), i, stops[i])->iconid;

        // Check to see if it is Rbin (we bump the count and continue looking)
        if ( testIcon == ROBIN_HOOD )
        {
            hasRobin = true;
        }
        else
        {
            // If we haven't found our first non Robin, store it off.
            if ( iconThatIsNotRobin == BLANK )
            {
                iconThatIsNotRobin = testIcon;
            }
            // If we have found our fist non robin icon, and this icon was not robin
            // and it is not the same as the first non Robin icon, then our evaluation stops.
            else if ( iconThatIsNotRobin != testIcon )
            {
                break;
            }
        }
    }

    switch ( iconThatIsNotRobin )
    {
		case NINE:
			if ( i == 5 )
			{
                result = EVT_FIVE_NINE;
			}
			else if (i == 4)
            {
                result = EVT_FOUR_NINE;
			}
			else if (i == 3)
            {
                result = EVT_THREE_NINE;
			}
			break;
 
		case TEN:
			if ( i == 5 )
			{
                result = EVT_FIVE_TEN;
			}
			else if (i == 4)
            {
                result = EVT_FOUR_TEN;
			}
			else if (i == 3)
            {
                result = EVT_THREE_TEN;
			}
			break;

        case JACK:
			if ( i == 5 )
			{
                result = EVT_FIVE_JACK;
			}
			else if (i == 4)
            {
                result = EVT_FOUR_JACK;
			}
			else if (i == 3)
            {
                result = EVT_THREE_JACK;
			}
			break;

        case QUEEN:
			if ( i == 5 )
			{
                result = EVT_FIVE_QUEEN;
			}
			else if (i == 4)
            {
                result = EVT_FOUR_QUEEN;
			}
			else if (i == 3)
            {
                result = EVT_THREE_QUEEN;
			}
            break;		
		
        case KING:
			if ( i == 5 )
			{
                result = EVT_FIVE_KING;
			}
			else if (i == 4)
            {
                result = EVT_FOUR_KING;
			}
			else if (i == 3)
            {
                result = EVT_THREE_KING;
			}
			break;

        case ACE:
			if ( i == 5 )
			{
                result = EVT_FIVE_ACE;
			}
			else if (i == 4)
            {
                result = EVT_FOUR_ACE;
			}
			else if (i == 3)
            {
                result = EVT_THREE_ACE;
			}
            break;

        case BAG_OF_COINS:
			if ( i == 5 )
			{
                result = EVT_FIVE_BAG_OF_COINS;
			}
			else if (i == 4)
            {
                result = EVT_FOUR_BAG_OF_COINS;
			}
			else if (i == 3)
            {
                result = EVT_THREE_BAG_OF_COINS;
			}
			else if (i == 2)
            {
                result = EVT_TWO_BAG_OF_COINS;
			}
            break;

        case BOW_AND_ARROW:
			if ( i == 5 )
			{
                result = EVT_FIVE_BOW_AND_ARROW;
			}
			else if (i == 4)
            {
                result = EVT_FOUR_BOW_AND_ARROW;
			}
			else if (i == 3)
            {
                result = EVT_THREE_BOW_AND_ARROW;
			}
			else if (i == 2)
            {
                result = EVT_TWO_BOW_AND_ARROW;
			}
            break;

        case MAID_MARION:
			if ( i == 5 )
			{
                result = EVT_FIVE_MAID_MARION;
			}
			else if (i == 4)
            {
                result = EVT_FOUR_MAID_MARION;
			}
			else if (i == 3)
            {
                result = EVT_THREE_MAID_MARION;
			}
			else if (i == 2)
            {
                result = EVT_TWO_MAID_MARION;
			}
            break;

        case ENEMY:
			if ( i == 5 )
			{
                result = EVT_FIVE_ENEMY;
			}
			else if (i == 4)
            {
                result = EVT_FOUR_ENEMY;
			}
			else if (i == 3)
            {
                result = EVT_THREE_ENEMY;
			}
			else if (i == 2)
            {
                result = EVT_TWO_ENEMY;
			}
            break;

        case CASTLE:
        case ARCHERY_BOARD:
        case ROBIN_HOOD:
            break;

        default:
            // Unknown icon type
            ASSERT(false);
            break;
    }

    // If we found a Robin during evaluation,
    // and we had a winning event then we had
    // a Robin Hood substitution.  Add the note.
    if ( result > EVT_LOSER && hasRobin ) 
    {
        multiplier *= MULTIPLIER_ROBIN_HOOD_SUBSTITUTE;
        spinline->addNote(NOTE_ROBIN_HOOD_SUBSTITUTE);
    }

    rtnresult = (uint8) result;
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::classifyScatters()   
///
/// @param   spin       Pointer to the spin with stop data.
///
/// This is an override of the framework method.  
/// It determines if the current spin merits free spins or scatter payments.
////////////////////////////////////////////////////////////////////////////
void 
PrinceOfSherwoodGuts::classifyScatters(SlotSpin *spin)
{
	uint8 numArcheryBoards				= 0;
	uint8 numCastles					= 0;
    int32 archeryBoardScatterPositions  = 0;
    int32 castleScatterPositions		= 0;
	uint8 stop							= 0;
	uint8 whichItem						= BLANK;
    uint8 position						= 0;
    uint8 multiplier					= 1;
	uint8 noteid                        = 0;
    
	spin->clearScatters();

	// If the current game mode is normal, then
    // check to see if the player won the progressive.
	if (getGameModeId() == MODE_NORMAL ) 
	{
		if ( getRandomProgressiveJackpotResult(spin->getSpinLineCount()) ||
			 m_bForceRandomJackpot)
        {
	        spin->addScatter( 0, 
                              getPayout(EVT_RANDOM_PROGRESSIVE_WINNER)->payoutAmount, 
                              1,
                              true,
                              EVT_RANDOM_PROGRESSIVE_WINNER,
                              0 );
        }
    }

    // Next, check all the icons at each reel/row position.
    // We are looking for castles and archery boards.
    // Both of these contribute to the scatter/feature triggers.
  	for (int reel = 0; reel<5; reel++)
	{
    	for (int row = 0; row < 3; row++)
		{
            position = (row*5)+reel;

			stop = relativeWheelPosition(getGameModeId(), reel, spin->getStops()[reel], row);
			whichItem = getIcon(getGameModeId(), reel, stop)->iconid;
			
			if ( whichItem == ARCHERY_BOARD )
			{
				if ( numArcheryBoards == reel )
				{
					numArcheryBoards++;
					archeryBoardScatterPositions += 1<<position;
				}
            }
            else if ( whichItem == CASTLE )
            {
				numCastles++;
                castleScatterPositions += 1<<position;
            }            
		} // row
	} // reel

	if ( numCastles > 0 || numArcheryBoards > 0 )
	{
		// During archery feature there are multipliers applied.
        if ( getGameModeId() == MODE_ARCHERY_FEATURE )
        {
            noteid = NOTE_ARCHERY_FEATURE;
            multiplier *= getFeatureGameMultiplier();
        }
	}

    // If we found any castle icons, we might
    // have a scatter winner.  If there is only
    // one castle, then this will be a scatter miss.
    // We still send a scatter record so the client
    // can highlight the position and/or play 
    // an anticipation sound on the reel.
	if (numCastles > 0 )
    {
        uint8 payouttypeid = EVT_LOSER;

	    switch ( numCastles )
	    {
	       case 1:
                payouttypeid = EVT_SCATTER_NEAR_MISS;
                break;

           case 2: 
                payouttypeid = EVT_TWO_CASTLE;
                break;

	       case 3: 
                payouttypeid = EVT_THREE_CASTLE;
                break;

	       case 4: 
                payouttypeid = EVT_FOUR_CASTLE;
                break;

           case 5: 
                payouttypeid = EVT_FIVE_CASTLE;
                break;
	    };

        int32 nPayout = getPayout(payouttypeid)->payoutAmount * ( spin->getSpinLineCount());

        increaseTotalWin(nPayout*multiplier);

        // Let's create a scatter record for the
        // Castles.
	    SlotScatter* pScatter = spin->addScatter( castleScatterPositions, 
                                                  nPayout*getBetPerLine(),
                                                  multiplier,
                                                  false,
                                                  payouttypeid,
                                                  0 );

        // If the multiplier is > 1 report the note
        // that explains why it is greater than 1.
        if ( multiplier > 1 )
        {
            pScatter->addNote(noteid);
        }
	}

	if ( numArcheryBoards > 0 )
	{
		// If we are already in a feature then 
		// all we can do is win the archery board scatter.
		if ( getGameModeId() == MODE_ARCHERY_FEATURE )
		{
			uint8 payouttypeid = EVT_LOSER;

			switch ( numArcheryBoards )
			{
			   case 1:
					payouttypeid = EVT_SCATTER_NEAR_MISS;
					break;

			   case 2: 
					payouttypeid = EVT_TWO_ARCHERY_BOARD;
					break;

			   case 3: 
					payouttypeid = EVT_THREE_ARCHERY_BOARD;
					break;

			   case 4: 
					payouttypeid = EVT_FOUR_ARCHERY_BOARD;
					break;

			   case 5: 
					payouttypeid = EVT_FIVE_ARCHERY_BOARD;
					break;
			};

			int32 nPayout = getPayout(payouttypeid)->payoutAmount * ( getNumLinesBet());

		    increaseTotalWin(nPayout*multiplier);

			// Let's create a scatter record for the
			// Archery boards.
			SlotScatter* pScatter = spin->addScatter( archeryBoardScatterPositions, 
													  nPayout*getBetPerLine(),
													  multiplier,
													  false,
													  payouttypeid,
													  0 );

			// If the multiplier is > 1 report the note
			// that explains why it is greater than 1.
			if ( multiplier > 1 )
			{
				pScatter->addNote(noteid);
			}
		}
		else
		{
			// If there are 3 or more archery boards, and we were not already
			// in the feature, then it is time to start the sub game.
			if ( numArcheryBoards >= 3 )
			{
				initializeFeatureGame();
				setFeatureGameNumScatterSymbols(numArcheryBoards);
	
				spin->addScatter( archeryBoardScatterPositions, 
								  0,
								  0,
								  false,
								  EVT_ARCHERY_GAME_BONUS,
			    				  0 );
			}
			else
			{
				spin->addScatter( archeryBoardScatterPositions, 
								  0,
								  0,
								  false,
								  EVT_FEATURE_NEAR_MISS,
			    				  0 );
			}
		}
    }   
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::isValidGuts()   
///
/// @return	 bool8      True if gut is valid.    
///
/// This helper method is used to the current gut ID is valid.
////////////////////////////////////////////////////////////////////////////
bool8 
PrinceOfSherwoodGuts::isValidGuts()
{
    return (getGutsId() >= 700 && getGutsId() < 799);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::getGameModeMultiplierAndNoteId( uint8& nGameModeMultiplier, uint8& nNoteId )   
///
/// @param	 nGameModeMultiplier    Returns the new multiplier based on the game mode.
/// @param   nNoteId                Returns the note Id associated with the game mode.
///
/// This helper method is get the game mode note and multiplier.
////////////////////////////////////////////////////////////////////////////
void 
PrinceOfSherwoodGuts::getGameModeMultiplierAndNoteId( uint8& nGameModeMultiplier, uint8& nNoteId )
{
	// During archery feature there are multipliers applied.
    if ( getGameModeId() == MODE_ARCHERY_FEATURE )
    {
        nNoteId = NOTE_ARCHERY_FEATURE;
        nGameModeMultiplier *= getFeatureGameMultiplier();
    }
    else
    {
        SlotGuts::getGameModeMultiplierAndNoteId( nGameModeMultiplier, nNoteId );
    }
}
 
////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::setFeatureGameMultiplier(int32 nFeatureGameMultiplier) 
///
/// @param   nFeatureGameMultiplier  The multiplier awarded for the feature.
///
/// This is a mutator to set the multiplier applied to the feature game.
////////////////////////////////////////////////////////////////////////////
void 
PrinceOfSherwoodGuts::setFeatureGameMultiplier(int32 nFeatureGameMultiplier)
{
    m_subGame->update(SGDIDX_FEATURE_MULTIPLIER,nFeatureGameMultiplier);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::getFeatureGameMultiplier() const 
///
/// @return  int32   The multiplier awarded for the feature.
///
/// This is an accessor mutator method to get the multiplier applied to the feature game.
////////////////////////////////////////////////////////////////////////////
int32 
PrinceOfSherwoodGuts::getFeatureGameMultiplier() const
{
    return m_subGame->getData(SGDIDX_FEATURE_MULTIPLIER);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::setFeatureGameNumFreeGames(int32 nNumFreeGames) 
///
/// @param   nNumFreeGames  The number of free games awarded.
///
/// This is a mutator method to set the number of free games awarded on this feature game.
////////////////////////////////////////////////////////////////////////////
void  
PrinceOfSherwoodGuts::setFeatureGameNumFreeGames(int32 nNumFreeGames)
{
    m_subGame->update(SGDIDX_FEATURE_NUM_FREE_GAMES,nNumFreeGames);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::getFeatureGameNumFreeGames() const
///
/// @return  int32   The number of free games awarded.
///
/// This is an accessor method used to get the number of free games awarded on this feature game.
////////////////////////////////////////////////////////////////////////////
int32 
PrinceOfSherwoodGuts::getFeatureGameNumFreeGames() const
{
    return m_subGame->getData(SGDIDX_FEATURE_NUM_FREE_GAMES);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::setFeatureGameState(int32 nState)
///
/// @param   nState  The current stage of the feature game.
///
/// This is a mutator method used to set the current stage of the feature game.
////////////////////////////////////////////////////////////////////////////
void 
PrinceOfSherwoodGuts::setFeatureGameState(int32 nState)
{
    m_subGame->update(SGDIDX_FEATURE_STATE,nState);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::getFeatureGameState() const 
///
/// @return  int32   The current stage of the feature game.
///
/// This is an accessor method to get the current stage of the feature game.
////////////////////////////////////////////////////////////////////////////
int32 
PrinceOfSherwoodGuts::getFeatureGameState() const
{
    return m_subGame->getData(SGDIDX_FEATURE_STATE);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::setFeatureGamePlayerShot(int32 nFeatureGamePlayerShot) 
///
/// @param   nFeatureGamePlayerShot  The score for the player's shot.
///
/// This is a mutator method to set the score for the player's shot.
////////////////////////////////////////////////////////////////////////////
void  
PrinceOfSherwoodGuts::setFeatureGamePlayerShot(int32 nFeatureGamePlayerShot)
{
    m_subGame->update(SGDIDX_PLAYER_SHOT,nFeatureGamePlayerShot);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::getFeatureGamePlayerShot() const 
///
/// @return  int32   The score for the player's shot.
///
/// This is an accessor method to get the score for the player's shot.
////////////////////////////////////////////////////////////////////////////
int32 
PrinceOfSherwoodGuts::getFeatureGamePlayerShot() const
{
    return m_subGame->getData(SGDIDX_PLAYER_SHOT);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::setFeatureGameNonPlayerShot(int32 nFeatureGameNonPlayerShot) 
///
/// @param   nFeatureGameNonPlayerShot  The score for the non player's shot.
///
/// This is a mutator method to set the score for the non player's shot.
////////////////////////////////////////////////////////////////////////////
void  
PrinceOfSherwoodGuts::setFeatureGameNonPlayerShot(int32 nFeatureGameNonPlayerShot)
{
    m_subGame->update(SGDIDX_NON_PLAYER_SHOT,nFeatureGameNonPlayerShot);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::getFeatureGameNonPlayerShot() const 
///
/// @return  int32   The score for the non player's shot.
///
/// This is an accessor method to get the score for the non player's shot.
////////////////////////////////////////////////////////////////////////////
int32 
PrinceOfSherwoodGuts::getFeatureGameNonPlayerShot() const
{
    return m_subGame->getData(SGDIDX_NON_PLAYER_SHOT);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::setFeatureGamePlayerArcherChoice(int32 nPlayerArcherChoice) 
///
/// @param   nPlayerArcherChoice  The archer chosen for the player.
///
/// This is a mutator method to change the archer chosen for the player.
////////////////////////////////////////////////////////////////////////////
void  
PrinceOfSherwoodGuts::setFeatureGamePlayerArcherChoice(int32 nPlayerArcherChoice)
{
    m_subGame->update(SGDIDX_PLAYER_ARCHER_CHOICE,nPlayerArcherChoice);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::getFeatureGamePlayerArcherChoice() const
///
/// @return  int32   The archer chosen for the player.
///
/// This is an accessor method to get the archer chosen for the player.
////////////////////////////////////////////////////////////////////////////
int32 
PrinceOfSherwoodGuts::getFeatureGamePlayerArcherChoice() const
{
    return m_subGame->getData(SGDIDX_PLAYER_ARCHER_CHOICE);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::setFeatureGameNonPlayerArcherChoice(int32 nNonPlayerArcherChoice) 
///
/// @param   nNonPlayerArcherChoice  The archer chosen for the non player.
///
/// This is a mutator method to change the archer chosen for the non player.
////////////////////////////////////////////////////////////////////////////
void  
PrinceOfSherwoodGuts::setFeatureGameNonPlayerArcherChoice(int32 nNonPlayerArcherChoice)
{
    m_subGame->update(SGDIDX_NON_PLAYER_ARCHER_CHOICE,nNonPlayerArcherChoice);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::getFeatureGameNonPlayerArcherChoice() const 
///
/// @return  int32   The archer chosen for the non player.
///
/// This is an accessor method to get the archer chosen for the non player.
////////////////////////////////////////////////////////////////////////////
int32 
PrinceOfSherwoodGuts::getFeatureGameNonPlayerArcherChoice() const
{
    return m_subGame->getData(SGDIDX_NON_PLAYER_ARCHER_CHOICE);
}


////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::setFeatureGameNumScatterSymbols(int32 nNumScatterSymbols) 
///
/// @param   nNumScatterSymbols  The number of scatter symbols that triggered the feature.
///
/// This is a mutator method to change the number of scatter symbols that triggered the feature.
////////////////////////////////////////////////////////////////////////////
void  
PrinceOfSherwoodGuts::setFeatureGameNumScatterSymbols(int32 nNumScatterSymbols)
{
    m_subGame->update(SGDIDX_NUM_SCATTER_SYMBOLS,nNumScatterSymbols);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::getFeatureGameNumScatterSymbols() const 
///
/// @return  int32   The number of scatter symbols that triggered the feature.
///
/// This is an accessor method to get the number of scatter symbols that triggered the feature.
////////////////////////////////////////////////////////////////////////////
int32 
PrinceOfSherwoodGuts::getFeatureGameNumScatterSymbols() const
{
    return m_subGame->getData(SGDIDX_NUM_SCATTER_SYMBOLS);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::initializeFeatureGame()  
///
/// Helper method called to initialize the feature game.
////////////////////////////////////////////////////////////////////////////
void 
PrinceOfSherwoodGuts::initializeFeatureGame()
{
	setGameCanComplete(false);
	setFeatureGameMultiplier(0);
	setFeatureGameNumFreeGames(0);
	setFeatureGameState(SGS_SELECT_ARCHER);
	setFeatureGamePlayerShot(0);
	setFeatureGameNonPlayerShot(0);
	setFeatureGamePlayerArcherChoice(SELECTED_NONE);
	setFeatureGameNonPlayerArcherChoice(SELECTED_NONE);
	setFeatureGameNumScatterSymbols(0);
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::processClientData()
///
/// @param   bonusGameType      The current type of bonus game.
/// @param   bonusDataCount     The number of integers passed from the client.
/// @param   bonusData			An array of integers passed from the client.
/// 
/// This is an override of the framework method.
/// 
////////////////////////////////////////////////////////////////////////////
bool8
PrinceOfSherwoodGuts::processClientData(uint8 bonusGameType, int32 bonusDataCount, int32 *bonusData)
{
	// Start by assuming that we need to reply to this message
	bool8 bReply = true;

	int32 nCurrentStage = getFeatureGameState();

	// If the game is in either of these states, the client should not be sending a playBonusGame message.
	if ( nCurrentStage == SGS_NONE || nCurrentStage == SGS_GAME_OVER )
	{
		ASSERT(false);
		bReply = false;
	}
	// Otherwise if we are in the stage where the player is selecting his archer
	// we expect that information to be passed in here as the first entry in 
	// the bonusData array.
	else if ( nCurrentStage == SGS_SELECT_ARCHER ) 
	{
		// Extract and assign the player's archer choice
		int32 nPlayerArcher = *bonusData;
		setFeatureGamePlayerArcherChoice( nPlayerArcher );
		
		// Determine the non player's archer.
		if ( nPlayerArcher == SELECTED_ROBIN )
		{
			setFeatureGameNonPlayerArcherChoice(SELECTED_ENEMY);
		}
		else if ( nPlayerArcher == SELECTED_ENEMY )
		{
			setFeatureGameNonPlayerArcherChoice(SELECTED_ROBIN);
		}
		// Unknown archer
		else
		{
			ASSERT(false);
		}

		setFeatureGameNonPlayerShot(getRandomValueFromProbabilityTable( PT_NON_PLAYER_SHOT));

		setFeatureGameState(SGS_NON_PLAYER_ARCHER_SHOOTS);
	}
	else if ( nCurrentStage == SGS_NON_PLAYER_ARCHER_SHOOTS )
	{
		int32 nPlayerShotPT = 0;

		// Choose the proper probability table for
		// the player archer based on the number of 
		// scatter symbols.
		switch ( getFeatureGameNumScatterSymbols() )
		{
			case 3:
				nPlayerShotPT = PT_PLAYER_SHOT_3_SCATTERS;
				break;

			case 4:
				nPlayerShotPT = PT_PLAYER_SHOT_4_SCATTERS;
				break;
			
			case 5:
				nPlayerShotPT = PT_PLAYER_SHOT_5_SCATTERS;
				break;

			// We should only get to this function with 
			// 3, 4, or 5 symbols.
			default:
				ASSERT(false);
				break;
		}

		// Use the probabilty tables to determine the score for each archer.
		setFeatureGamePlayerShot(getRandomValueFromProbabilityTable( nPlayerShotPT));

		setFeatureGameState(SGS_PLAYER_ARCHER_SHOOTS);
	}
	else if ( nCurrentStage == SGS_PLAYER_ARCHER_SHOOTS )
	{
		// If the player beat the non player, then he moves on, otherwise the game is over.
		if ( getFeatureGamePlayerShot() > getFeatureGameNonPlayerShot() )
		{
			int32 nPlayerFreeGamesPT = 0;

			// Choose the proper probability table for
			// the player archer based on the number of 
			// scatter symbols.
			switch ( getFeatureGameNumScatterSymbols() )
			{
				case 3:
					nPlayerFreeGamesPT = PT_PLAYER_SHOT_FG_3_SCATTERS;
					break;

				case 4:
					nPlayerFreeGamesPT = PT_PLAYER_SHOT_FG_4_SCATTERS;
					break;
				
				case 5:
					nPlayerFreeGamesPT = PT_PLAYER_SHOT_FG_5_SCATTERS;
					break;

				// We should only get to this function with 
				// 3, 4, or 5 symbols.
				default:
					ASSERT(false);
					break;
			}

			// Figure out how many free games they won.
			setFeatureGameNumFreeGames(getRandomValueFromProbabilityTable(nPlayerFreeGamesPT));

			setFeatureGameState(SGS_FIRE_ARROW_FOR_FREE_GAMES);
		}
		else
		{
			setFeatureGameState(SGS_GAME_OVER);
		}
	}
	else if ( nCurrentStage == SGS_FIRE_ARROW_FOR_FREE_GAMES ) 
	{
		int32 nPlayerMultPT = 0;

		// Choose the proper probability table for
		// the player archer based on the number of 
		// scatter symbols.
		switch ( getFeatureGameNumScatterSymbols() )
		{
			case 3:
				nPlayerMultPT = PT_PLAYER_SHOT_MULT_3_SCATTERS;
				break;

			case 4:
				nPlayerMultPT = PT_PLAYER_SHOT_MULT_4_SCATTERS;
				break;
			
			case 5:
				nPlayerMultPT = PT_PLAYER_SHOT_MULT_5_SCATTERS;
				break;

			// We should only get to this function with 
			// 3, 4, or 5 symbols.
			default:
				ASSERT(false);
				break;
		}

		// Figure out the multiplier for the free games.
		setFeatureGameMultiplier(getRandomValueFromProbabilityTable(nPlayerMultPT));

		// Set the next game state.
		setFeatureGameState(SGS_FIRE_ARROW_FOR_MULTIPLIER);
	}
	else if ( nCurrentStage == SGS_FIRE_ARROW_FOR_MULTIPLIER ) 
	{
		// They are done.
		setFeatureGameState(SGS_GAME_OVER);
	}
	// Unknown state
	else   
	{
		bReply = false;
		ASSERT(false);
	}


	if ( getFeatureGameState() == SGS_GAME_OVER && getGameCanComplete() == false )
	{
		int32 basepayoutamount;
		int32 totalmultiplier;
		int32 totalbonuspayoutamount;

		basepayoutamount = getBetPerLine() * getNumLinesBet();
		totalmultiplier = getFeatureGamePlayerShot() + getFeatureGameNonPlayerShot();
		totalbonuspayoutamount = basepayoutamount * totalmultiplier;

		if ( getFeatureGameNumFreeGames() > 0 )
		{
			incrementFreeSpins(getFeatureGameNumFreeGames());

			if ( getGameModeId() == 0 )
			{
				setGameModeId(MODE_ARCHERY_FEATURE);
			}
		}

		if ( getSlotSpin() )
		{
			addBonusGame(0, 0, basepayoutamount, totalmultiplier, totalbonuspayoutamount, 0);
			addBonusGame(0, 1, 0, 0, 0, getFeatureGameNumFreeGames());
		}

		// Update Feature Game Data for an audit trail.
		m_feature->setLevel( 1 );
		m_feature->update( SGDIDX_FEATURE_MULTIPLIER, getFeatureGameMultiplier(), true ); 
		m_feature->update( SGDIDX_PLAYER_SHOT, getFeatureGamePlayerShot(), true );
		m_feature->update( SGDIDX_NON_PLAYER_SHOT, getFeatureGameNonPlayerShot(), true );
		m_feature->update( SGDIDX_FEATURE_NUM_FREE_GAMES, getFeatureGameNumFreeGames(), true );
		m_feature->update( SGDIDX_PLAYER_ARCHER_CHOICE, getFeatureGamePlayerArcherChoice(), true );
		m_feature->update( SGDIDX_NON_PLAYER_ARCHER_CHOICE, getFeatureGameNonPlayerArcherChoice(), true );
		m_feature->update( SGDIDX_NUM_SCATTER_SYMBOLS, getFeatureGameNumScatterSymbols(), true );

		setGameCanComplete(true);

		setFeatureGameState(SGS_NONE);
		bReply = true;
	}

	return bReply;
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::hasSavedGames()
///
/// @param   bool8   True/False indicating if this machine supports saved gamees.
///
/// This is a framework override to determine if this machine supports saved games.
////////////////////////////////////////////////////////////////////////////
bool8
PrinceOfSherwoodGuts::hasSavedGames()
{
	return true;
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::getBonusGameState() const
///
/// @param   int32   The bonus game state.
///
/// This is a framework override to determine the bonus game state.
////////////////////////////////////////////////////////////////////////////
int32
PrinceOfSherwoodGuts::getBonusGameState() const
{
	return getFeatureGameState();
}


////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::setBonusGameState( int32 bonusGameState )
///
/// @param   bonusGameState   The bonus game state.
///
/// This is a framework override to set the bonus game state.
////////////////////////////////////////////////////////////////////////////
void
PrinceOfSherwoodGuts::setBonusGameState( int32 bonusGameState )
{
	setFeatureGameState(bonusGameState);
}


////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::preSpinClassifyResults()   
///
/// @param   spin       Pointer to the spin with stop data.
///
/// This method is overridden when running in debug spins mode to alter the reel stops.
////////////////////////////////////////////////////////////////////////////
void 
PrinceOfSherwoodGuts::preSpinClassifyResults( SlotSpin* spin )
{
	SlotGuts::preSpinClassifyResults(spin);
	return;
}

////////////////////////////////////////////////////////////////////////////
/// @fn 	 PrinceOfSherwoodGuts::Debug_SetLoserStops( uint8* pStops )
///
/// @param   pStops		The stops to set.
///
/// Base class override, returns a losing spin triggered by the debug tool
////////////////////////////////////////////////////////////////////////////
void PrinceOfSherwoodGuts::Debug_SetLoserStops( uint8* pStops )
{
	pStops[0]=0;
	pStops[1]=3;
	pStops[2]=0;
	pStops[3]=0;
	pStops[4]=0;
}